package dubbo.learn.handler;

import com.alibaba.fastjson.JSONObject;
import dubbo.learn.utils.SpringContextUtils;
import dubbo.learn.common.RequestVO;
import dubbo.learn.common.ResponseVO;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * @author zhouxl
 * 作为服务端拦截器，处理群聊天应用(多客户端通讯)
 */
@Slf4j
public class ServerHandlers extends SimpleChannelInboundHandler<String>  {



    @Override
    public void channelActive(ChannelHandlerContext ctx) {
    }


    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
        log.info(msg);
        RequestVO requestVO = JSONObject.parseObject(msg, RequestVO.class);
        log.info("requestVO:{}",requestVO);

        String serviceName = requestVO.getServiceName();
        Class<?> clazz = Class.forName(serviceName);
        Object bean = SpringContextUtils.getBean(clazz);

        Method[] methods = clazz.getMethods();
        Method method = Arrays.stream(methods).filter(m -> Objects.equals(m.getName(), requestVO.getMethodName())
                && (m.getParameterCount() == requestVO.getParamCount())
        ).findFirst().orElse(null);
        /**
         * 获取参数数组
         */
        Object[] paramArray = assemblyParamArray(method, requestVO);
        method.setAccessible(true);
        Object o = method.invoke(bean, paramArray);

        ResponseVO responseVO = new ResponseVO();
        responseVO.setRequestId(requestVO.getRequestId());
        responseVO.setContent(JSONObject.toJSONString(o));

        String result = JSONObject.toJSONString(responseVO);
        log.info("result:{}", result);
        Thread.sleep((long) (Math.random()*2000));
        ctx.channel().writeAndFlush(result);
    }

    private Object[] assemblyParamArray(Method method, RequestVO requestVO) {
        int parameterCount = method.getParameterCount();
        if (parameterCount == 0) {
            return new Object[0];
        }

        if (requestVO.getParamsJsonArray() != null && requestVO.getParamsJsonArray().size() != method.getParameterCount()) {
            throw new RuntimeException();
        }

        Object[] result = new Object[parameterCount];

        List<String> paramsJsonArray = requestVO.getParamsJsonArray();
        Class<?>[] parameterTypes = method.getParameterTypes();
        for (int i = 0; i < parameterTypes.length; i++) {
            String paramFromReq = paramsJsonArray.get(i);
            Class<?> parameterTypeClazz = parameterTypes[i];
            Object param = JSONObject.parseObject(paramFromReq, parameterTypeClazz);

            result[i] = param;
        }

        return result;
    }

    /**
     * 设备异常关闭
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx,Throwable cause)throws Exception{
        log.info(ctx.channel().id()+" 出错");
        ctx.close();
    }

}